/*
 * Copyright 2007-2009 Perttu "celeron55" Ahola <celeron55@gmail.com>
 *
 * This file is part of jukumagic.
 *
 * jukumagic is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * jukumagic is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with jukumagic.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef BOARD_H_
#define BOARD_H_

#include "common.h"
#include "objectcontainer.h"
#include "net.h"
#include "pin.h"
#include <wx/wx.h>
#include <list>
#include <vector>
#include <map>

class ConnectionMapNode
{
public:
	bool cut;
	bool narrowcut; //to right of the point
	std::list<int> cons;
};

class BoardChangeHandler
{
public:
	virtual void ContentsChanged(){}
	virtual void SelectionChanged(){}
};

class RatsNest;
class Netlist;

class Board : public ObjectContainer
{
private:
	bool m_conmap_needs_refreshing;
	int m_w_holes;
	int m_h_holes;
	double m_savescale;
	std::vector<ConnectionMapNode> m_conmap_cache;
	std::list<BoardChangeHandler*> m_change_handlers;
	
	void ChildChanged(ObjectChangeType type, JukuObject *obj);
	void SelfChanged(ObjectChangeType type);

	void DrawObjectsIfNeeded(wxDC &dc, wxWindow *window, wxPoint origin, JukuObjectType type, int side);

	void GetConnectionMap(std::vector<ConnectionMapNode> &nodes);
	std::vector<ConnectionMapNode>& GetCacheConnectionMap();
	void CalcConnectionMapIfNeeded();
	
	bool GetContinuousCopperExtent(int x, int y, int *x1, int *x2,
			std::vector<ConnectionMapNode> &nodes, int w);
	bool RecursiveIsConnected(int p1, int p2, std::set<int> &points,
			std::vector<ConnectionMapNode> &nodes, int w);
			
	void ChangedSomething();
	void ChangedSelection();
	
public:
	std::set<int> m_hilighted_points;
	bool m_ratsnest_visible;
	RatsNest *m_ratsnest;
	
	void InitValues();
	
	Board();
	Board(unsigned int w_holes, unsigned int h_holes);
	~Board();

    JukuObjectType GetType(){ return TYPE_BOARD; }
	const wxChar * GetShortString(void){return NULL;}
	const wxChar * GetTypeString(void){return _("Board");}

	void WriteXML(TiXmlNode* root);
	static JukuObject* ReadFromXMLElement(TiXmlElement* element);

	void SetSize(unsigned int w_holes, unsigned int h_holes);
	void Draw(wxDC &dc, wxWindow *window, wxPoint origin);

	int GetW(){ return m_w_holes; }
	int GetH(){ return m_h_holes; }
	void SetW(int w){ m_w_holes = w; ChangedSomething(); }
	void SetH(int h){ m_h_holes = h; ChangedSomething(); }
	double GetSaveScale(){ return m_savescale; }
	void SetSaveScale(double scale){ m_savescale = scale; }

	JukuObject* GetSelectedObject(int click_x, int click_y);
	std::set<JukuObject*> GetSelectedObjects(int x1, int y1, int x2, int y2,
			bool touch_is_enough);
			
	const std::set<JukuObject*> & GetSelectedObjects(){ return ObjectContainer::GetSelectedObjects(); }
	
	Pin* GetPinByNetPin(NetPin &p);
	BoardPoint FindNetPinPlace(NetPin &p);
	//generates supposed-to-be NetPin from that point's component & pin information
	//returns false if there's no pin at the point
	bool GetNetPinByPoint(BoardHPoint p1, NetPin *npin);

	bool GetConnected(BoardHPoint p1, std::set<int> &points);
	bool IsConnected(BoardHPoint p1, BoardHPoint p2);

	BoardHPoint IntPointToBoardHPoint(int ip);
	
	void AddChangeHandler(BoardChangeHandler *h);
	void RemoveChangeHandler(BoardChangeHandler *h);

	void GetComponents(std::vector<Component*> &components);

	Component* FindComponent(wxString refdes);
	
	void ThrowComponent(Component *component);

	void CollectOverBoardComponents();
};

#endif
